Peripheral computer hardware such as printers, scanners, modems, etc, and their appropriate software are not integral parts of a computer or its operating system. As supplementary devices not integral to the system, they are not already programmed into the operating system, and so need their own specific code to allow them integrate into the system. These specific code packages are referred to as device drivers, and are delivered with the purchase of each new device. In many cases the operating system itself locates and downloads the appropriate device drivers so the users do not have to do this themselves—these are known as plug and play systems, so called because you simply “plug” it into the system, which then locates the driver enabling the device to start to “play”. This works because a large number of device drivers are bundled with the Operating System (“OS”) for the latest Windows OS versions in particular, and the feature for finding the driver needed automatically by searching online repositories is also included. This means that a user can simply connect a new device without having any driver, and the OS will manage to “make it run” automatically without any user intervention.
Device drivers handle and control the interaction with the hardware platform and operating system with which they work. Usually one device driver can handle only a single operating system version and only a single hardware/processor platform. Because of this limitation, whenever a device needs to be run either on a different operating system (or different version) or on a different hardware platform, a new device driver (or an update if available) is needed or the device will not run.
The great majority of device drivers are designed to work in kernel-mode, meaning that when a device driver crashes, it is very probable that the whole system will crash, generating a blue screen. Also, if malicious code is inserted within a driver and is executed once that driver has been installed, the malicious code can access all of the kernel and central processing unit (CPU) components because it is run in kernel mode. So should a driver containing a virus be installed, it is very likely to have disastrous and potentially fatal effects on the underlying platform.
To ensure that drivers installed on operating systems contain no defective, incompatible or malicious code, operating system vendors have introduced measures to control drivers that are installed on them. An example is the Microsoft® Windows® driver signing process. Microsoft® signs drivers that it deems to be 100% compatible with Microsoft® Windows® operating systems, and have no unsafe code. During installation, a device driver that is not signed is rejected. There are two problems with this approach. First, driver signing is expensive for hardware vendors. Second, hardware vendors must hand their drivers to the operating system's vendor for inspection. This can give rise to the feeling of unwanted interference by the operating system's vendor from the point of view of the hardware vendor.
In typical network environments, only users with administrator rights are allowed to install devices. This limitation is applied so that no user can install unsafe drivers that can influence the server and network experience of other users of the same server or network. As it is impossible to give administrator rights to every user for obvious security reasons, this limitation prevents users from installing their own personal peripheral devices without having to go through the administrator.
The present invention was inspired by the fact that peripheral hardware devices and the appropriate software are distributed with their own individual device drivers, which in most cases are written for a single operating system (or at most a very small number of operating systems). Yet today the list of possible devices that can be added to a modern computer system is virtually endless. Even the more basic systems set up in a user's home will probably have a number of peripheral devices added, such as printers, scanners, external hard disks, etc. Each of these devices needs a device driver. When this is expanded to a multiple user and server corporate network, the number of installed device drivers can be practically impossible to properly maintain and keep up to date. If there are frequent driver conflicts, this can seriously restrict the day to day operation of a large network.
To provide more depth as to how a solution to the above described problems can be applied, it is necessary to provide more of a context on the drivers and how they operate.
FIG. 1 gives an overview of the runtime context of a conventional device driver. The applications (110) wishing to use a universal serial bus (USB) device (100) sends a driver use request (120) to the host operating system (140) within the host operating system runtime environment (102). The USB controller (105) obtains information from the USB device (100), enumerates it, adds in events such as hardware interrupts (170), and passes this on to the host operating system (140).
The host operating system (140) then communicates with the device driver (150) via system calls and kernel application programming interfaces (APIs) calls (195) and the driver model (130) to obtain the information needed to control the USB device (100). Where required, function calls (185) are further placed to other drivers or kernel-level dynamically loaded files (.sys/.dll) (180) for necessary data.
The response from the device driver (150) returns to the host operating system (140) and then back to the USB device (100) routed through the input/output (I/O) ports (190).
Finally, a set of assembly instructions (165) specific to the processors for which it was developed that access and manipulate the underlying hardware resources, such as the processor's registers and memory, are sent from the device driver (150) to the host processor CPU (160). The processor's instruction set allows a driver to manipulate its I/O ports. However, in this conventional driver model, device drivers do not manipulate ports directly, as this is usually done by the underlying bus drivers.
The context of the device driver (150) can be defined by analyzing the entities with which it communicates and how this communication takes place. The first entities are the applications (110) controlling the device (100) (for simplicity only one application will be referred to in the text below). When a user accesses the application to impact certain features or functions of the device, it seems as if the application (110) is controlling the device (100). However, the process is not that simple. When the user executes a function on the device, the application (110) forms a device request package (120) that contains information about the device, the data to send to the device and other relevant information. It sends this package (120) to the host operating system (140) on which it is currently running (e.g., Microsoft® Windows®) through a device Input/Output (I/O) Control function call that is part of the operating system's standard set of API calls. The APIs can be seen as the only way that applications can communicate with the operating system's kernel, and the only way for applications (110) to communicate with the CPU (160) resources and devices is by calling these APIs.
Once the application (100) sends this device request package (120) to the host operating system, it waits for a return value that indicates whether or not the request has been successful. Any operations performed by the kernel and any other components with which it communicates are abstracted from the application (110). So from the point of view of the application, if the value returned by the device I/O control indicates that the operation has been successful, it assumes that the attribute has been changed to the one requested. If the value indicates an unsuccessful operation, there are ways for the application (110) to get more information about what type of failure occurred. The host operating system (140) thus acts as an intermediary between the application (110) and the device driver (150). The host operating system (140) presents the information that the application (110) inserted in the request package into a different standard package. This package then presents the information that the driver (150) needs to control the device (100). This communication will be discussed in more detail later.
From the hardware point of view, there are instances in which a USB device (100) needs to communicate to the device driver (150) to notify the driver of an external event that has happened. As in the case of the communication between the application (110) and the driver (150) above, the host operating system (140) acts as intermediary between the device (100) and its driver (150). The host operating system (140) enumerates events such as hardware interrupts (170) that can be generated by connected devices (100). The USB controller (105) contains an enumeration of all USB devices (100) connected to it, and adds information indicating which USB device (100) generated the interrupt (i.e., the device's descriptor). The USB controller (105) then waits for the host operating system (140) to perform the appropriate action. So ultimately the device driver (150) is the component that controls the response actions that the device (100) must take.
Whenever a USB device (100) is connected, a similar procedure takes place when the USB controller (105) detects the new device (100), in that it obtains information about the new device, enumerates it and then informs the operating system (140) about it. The reverse process happens when a USB device (100) is disconnected, and similar processes happen when a device (100) is powered on and off, set to or resumed from the sleep state.
The above scenario explains generally how hardware interrupts allow the communication from the devices to the host operating system. The reverse type of communication—from the host operating system (140) to the USB devices (100)—is done through I/O ports (190). The host operating system (140) passes both a control instruction (i.e., the instruction for the device to execute a function) and data (the description of specific parameters necessary for the requested function) through I/O ports (190). I/O ports (190) can also be used in the reverse direction (from the device to the host operating system) and data communication can also be handled by the host operating system through memory mapping. However, details about these functions are unnecessary to the understanding of the subject matter of this application. In summary, the host operating system (140) abstracts communication with the device driver (150) from the USB device (100) and USB controller (105). This means that it does not matter which device driver (150) is handling a particular device (100) as long as the USB device (100) and USB controller (105) can communicate with the host operating system (140) in the standard way specified.
By looking at these two scenarios (communication to/from the application and to/from the device) from the device driver's point of view, one can appreciate more the abstractions offered by the operating system that allows device drivers to be built in a standardized way according to the operating system they run on and not specifically according to the device they control. Every operating system provides a driver model that simplifies driver implementation (such as the Microsoft® Windows® driver model, or WDM). The functionality of the driver is implemented within a series of dispatch routines and some other special functions. Thus, for example, there is a standard function (dispatch routine) that is called when the application calls the device I/O control command, another standard function that is called when the device is connected, another when the operating system starts up, and so on. So from the point of view of the driver it does not make a difference if the source of the request is originating from an application, from the operating system itself, or from the hardware platform currently hosting the device.
Inside the implementation of these “special” functions, the device driver implements all of the functionality needed by the device depending on its features. However, the host operating system (140) provides a number of system calls or kernel-level APIs (195). These are similar to the APIs used by the applications (as already described); however, unlike those used by the applications, they are only accessible at the kernel-level, as they manipulate kernel resources that are not available for applications. As a result, while the driver (150) is servicing a request coming from the host operating system (140), it calls the host operating system (140) again to perform generic tasks. These tasks are mostly memory operations, such as the allocation and freeing of chunks of memory.
Apart from the kernel APIs (195), drivers can also call functions from kernel level dynamically loaded libraries (180), via function calls (185). These libraries are not part of the kernel and can also be developed by third party developers. However, when the device driver (150) is loaded, the operating system (140) loads these libraries (180) inside the kernel so that their functions are available for the device driver (150) to call. These libraries (180) can even be drivers themselves. For example, most digital camera device drivers use a generic camera driver that provides general functionality for every camera.
The final line of communication happens between the device driver (150) and the host processor (160) itself. The driver's internal code is made up of a set of assembly instructions (165) that are specific to the processor for which it was developed. So, for example, if a device driver was developed to run on an Intel®Pentium processor, its internal code will be a set of Intel® x86 assembly instructions. These instructions access and manipulate the underlying hardware resources, such as the processor's registers and memory. It should be noted that the processor's instruction set allows a driver to manipulate its I/O ports. However in the conventional driver model, device drivers do not manipulate ports directly, as this is usually done by the underlying bus drivers.
Due to the large number and variations of possible devices that can be connected to a computer system and the possible range of versions, platforms and systems with which they may be compatible, it is not possible to have dedicated device driver software for all possible devices contained within the operating system. The present invention solves this problem by providing one generic driver that handles all the interfaces involved in communication between the peripheral device and the system, therefore eliminating the need to have multiple device drivers installed for each version, platform and system in use, ensuring that while using the generic driver, the user is not putting the system's stability or security at risk in any way. If this happens, the generic driver either finds a way to obtain the same functionality without such breaches, limits its functionality, or stops the device.
The generic driver will detect whether any part of the functionality implemented within the device driver puts the underlying platform's security or stability at risk. If a security or stability risk is identified, then the action taken depends particularly on the type of stability or security risk identified. Possible actions that can be taken when such a breach is detected may include: 1) stopping the driver from performing the task that might cause the breach and showing a warning to the user (instead of allowing it to crash the whole system); or 2) taking alternative action that would allow the driver to continue performing the required task in a safe way. To do this, every type of breach would have to be analyzed individually, and the alternative action would have to be customized for every type of breach.
No research about individual cases causing these risks has yet been done, although a good idea can be obtained by looking at what Microsoft® is developing with Static Driver Verifier, Driver Verifier and Pre FAST discussed below. The main difference between these tools and the system shown here is that these tools are used by developers to help them produce better drivers—i.e., having the least possible system security/stability breaches. If a developer tests their driver and a security or stability breach is detected, then they can modify the driver code. The generic driver acts on drivers already distributed to users and hence their sources cannot be modified.
Other attempts have been made to address the situation where peripheral hardware devices should be able to run under an operating system for which no corresponding device driver is available. But these solutions are much more limited in scope than the present invention, and as such fall short of the capability of the generic driver solution that is disclosed here.
NDIS Wrappers for Linux® and BSD—NDIS Wrapper is an open-source project that aims to make NDIS-compliant NICs (Network Interface Cards), whose only available driver is for Microsoft® Windows®, run on Linux® and BSD. Its scope is limited to NICs and it executes drivers' local instructions directly on the host. This means that as it does not provide emulation, and it cannot handle drivers across different hardware platforms.
WINE32—WINE32 emulates Microsoft® Windows® APIs to run Microsoft® Windows® applications on Linux® and other POSIX-compliant operating systems. However it does not emulate kernel APIs and, as in the case of the NDIS Wrapper, it does not provide instruction emulation, because the hardware platform interoperability problem is not that significant for application-level programs. This means that through WINE32, an application for Microsoft® Windows® that controls a particular device can work on Linux® only if the corresponding Linux® driver is also installed on the system.
React-OS—React-OS is a project whose objective is to implement an operating system containing all the interface functionality of Microsoft® Windows®. It is not intended to be a Windows® clone; instead, it attempts to imitate Windows® behavior to such an extent that any hardware and software can run on or be handled by it in an identical way as in Windows®. So theoretically, a device without a driver that can handle it on Linux® can still run on Linux® by installing React-OS on Linux® as a guest operating system, and then installing its driver on the guest. However, this involves buying and installing a whole operating system and not just what is needed to make the device work. Also this solution does not provide the instruction emulation that makes cross-hardware-platform emulation possible.
LibUSB—LibUSB is an API that allows user level applications to access a USB device without needing to have a device driver actually installed on the system. It provides an interface containing a number of functions that can be called, each of which provides generic functions such as detecting plugged USB devices, transferring data packets through the USB hub to and from a USB device, etc. While it is true that some devices can work without having a driver available, only generic functionality is implemented within LibUSB, meaning that any particular functionality provided only by the device driver will not work. Again, this solution does not provide instruction emulation.
Various patents and patent applications also provide insight into what has gone before. See for example, U.S. Pat. Nos. 7,558,723; 7,437,613; 6,393,495; 6,269,408; and U.S. Patent Application Nos. 2009/0089815; 2011/0119666; 2008/0028401; 2007/0271557; and 2007/0050765; the entireties of which are incorporated by reference herein.